import type cardType from "../cardType/cardType"
import { cardScriptRun } from "./cardScript"

//修改此项时同时检查 function checkCard
export default class card {
    type: string
    data: { [key: string]: col }
    constructor(type?: string, data?: { [key: string]: col }) {
        this.type = type ?? ""
        this.data = data ?? {}
    }
}
type col = string | col[]

/**
 * 检查并转换一个col值为string|number
 * @returns 返回原值如果col为string|number，否则返回null
 */
function checkValue(data: col | null): string | null {
    if (data == null || data instanceof Array) {
        return null
    } else {
        return data
    }
}

/**
 * 检查并转换一个col值为array
 * @returns 返回原值如果col为array，否则返回null
 */
function checkArray(data: col | null): col[] | null {
    if (data == null || !(data instanceof Array)) {
        return null
    } else {
        return data
    }
}

/**
 * 安全的按照index组获取col下的某个值
 * @returns 获取的值,如果对应的index不存在则返回null
 */
function cardGetIndex(data: col, index: number[]): col | null {
    if (index.length == 0) return data
    let d = checkArray(data)
    if (d == null) return null
    let i = index[0]
    let newIndex: number[] = index.slice(1)
    if (newIndex.length == 0) {
        return d[i]
    } else {
        return cardGetIndex(d[i], newIndex)
    }
}

/**
 * 从一个card对象中获取某个key-index的方法
 * @returns 查询结果，如果没有对应的值，则返回null
 */
export function cardGet(card: card, dataKey: string, indexs?: number[]): string | null {
    //console.log(dataKey);

    if (card == undefined) return ''
    if (indexs == undefined || indexs.length == 0) {
        return checkValue(card.data[dataKey])
    }
    return checkValue(cardGetIndex(card.data[dataKey], indexs))

}

/**
 * 安全的按照index组设定col下的某个值
 */
function cardSetIndex(data: col[], index: number[], value: string) {

    let i = index[0]
    let newIndex: number[] = index.slice(1)
    if (data[i] == null || !(data[i] instanceof Array)) {
        data[i] = []
    }
    if (newIndex.length == 0) {
        if (data.length < i) data.length = i
        data[i] = value
    } else {
        cardSetIndex(data[i], newIndex, value)
    }
}

/**
 * 从一个card对象中设置某个key的方法
 */
export function cardSet(card: card, dataKey: string, value: string | undefined, index?: number[]) {
    //console.log(`dataKey:${dataKey} ;value:${value} ;index:${index}`);
    if (card == undefined) return
    if (index == undefined || index.length == 0) {
        if (value == undefined) {
            delete card.data[dataKey]
        } else {
            card.data[dataKey] = value
        }
    } else {
        if (card.data[dataKey] == null || !(card.data[dataKey] instanceof Array)) {
            card.data[dataKey] = []
        }
        cardSetIndex(card.data[dataKey], index, value ?? '')

        if (card.data[dataKey].length == 0) delete card.data[dataKey]
    }
}

/**
 * 获取一个card对象的多个key-index长度中的最大值
 * @param keys 所有参与的key
 * @param index 所有key共同使用的index
 */
export function cardKeyLength(card: card, keys: string[], index: number[]) {
    if (card == undefined) return 0
    //console.log(index);

    let length = 0
    for (const key of keys) {
        let array = checkArray(cardGetIndex(card.data[key], index)) ?? []
        //console.log(array)
        if (length < array.length) length = array.length

    }
    return length
}

/**
 * 对一个card对象的多个key-index下的数组执行方法
 * @param keys 所有参与的key
 * @param index 所有key共同使用的index
 * @param callback 执行的方法
 */
export function cardModifyArray(card: card, keys: string[], index: number[], callback: (array: Array<Object>) => void) {
    if (card == undefined) return
    //console.log(index);
    for (const key of keys) {
        //console.log(cardGetIndex(card.data[key], index))
        callback(checkArray(cardGetIndex(card.data[key], index)) ?? [])
    }
}

/**
 * 检查并移除对一个card对象的多个key-index下的数组空行（仅当所有key-index都为空时移除）
 * @param keys 所有参与的key
 * @param index 所有key共同使用的index
 */
export function cardRemoveEmptyRow(card: card, keys: string[], index: number[]) {
    if (card == undefined) return
    let arrays: col[][] = []
    for (const key of keys) {
        arrays.push(checkArray(cardGetIndex(card.data[key], index.slice(0, -1))) ?? [])
    }
    let empty = true
    let i = 0
    while (empty && arrays.length > i) {
        let data = arrays[i][index[index.length - 1]]
        empty = (data === undefined || (data as string | col[]).length === 0)
        i++
    }
    if (empty) {
        for (const arr of arrays) {
            arr.splice(index[index.length - 1], 1)
        }
    }
}
export function cardReadCommonKey(card: card, cardType: cardType, key: string) {
    let value = cardType.commonKeys[key]
    if (typeof value == 'string') {
        return cardGet(card, value)
    } else {
        return cardScriptRun(card, [], value).toString()
    }
}
export function checkCard(obj: any): card | undefined {
    if (typeof obj == 'object') {
        if (typeof obj.type == 'string' && typeof obj.data == 'object') {

            let result = new card(obj.type)
            for (const key of Object.keys(obj.data)) {
                let col = checkCol(obj.data[key])
                if (col != undefined) result.data[key] = col
            }
            return result
        }
    }
    return
}
export function checkCol(obj: any): col | undefined {
    switch (typeof obj) {
        case "string":
            return obj
        case "object":
            if (obj instanceof Array) {
                let result:col[] =[]
                for (let i = 0; i < obj.length; i++) {
                    result[i] = checkCol(obj[i]) ?? ''
                }
                return result
            }
        case "number":
        case "bigint":
        case "boolean":
            return obj.toString()
        case "undefined": {
            return ''
        }
    }
    return
}